# authentication/serializers.py
from rest_framework import serializers
from rest_framework.exceptions import AuthenticationFailed
from django.contrib.auth import authenticate
from .models import Category, CulturalRelic, DiseaseImage,User
# ImageRecordImage, ImageRecordLineDrawing, PaintingLocationImage, Survey,User,Building, PaintingLocation, PaintingContent, MaterialTechnique, PreservationAssessment, HistoricalRecord, ImageRecord
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
import base64
from PIL import Image, ImageFile
from io import BytesIO
from .choices import (
    ROLE_CHOICES, BUILDING_TYPE_CHOICES, FUNCTION_CHOICES, PROTECTION_LEVEL_CHOICES,
    PAINTING_LOCATION_CHOICES, PAINTING_DIRECTION_CHOICES, PATTERN_CHOICES,
    COLOR_CHOICES, COMPOSITION_CHOICES, PIGMENT_CHOICES, BINDER_CHOICES,
    GROUND_CHOICES, TECHNIQUE_CHOICES, RESTORATION_CHOICES, DISEASE_CHOICES,
    SEVERITY_CHOICES, ENVIRONMENT_CHOICES, AGE_BASIS_CHOICES, EQUIPMENT_CHOICES,
    LAB_TEST_CHOICES, FORMAT_CHOICES, STORAGE_LOCATION_CHOICES
)

from django.contrib.auth import get_user_model
User = get_user_model()
class CompressedImageField(serializers.ImageField):
    """自定义字段：压缩图片并返回Base64编码"""
    
    def __init__(self, max_size=(600, 600), quality=60, *args, **kwargs):
        self.max_size = max_size
        self.quality = quality
        super().__init__(*args, **kwargs)
    
    def to_representation(self, value):
        if not value:
            return None
            
        try:
            # 打开并压缩图片
            img = Image.open(value)
            img.thumbnail(self.max_size, Image.Resampling.LANCZOS)
            
            # 根据原始图片格式确定保存参数
            output_buffer = BytesIO()
            filename = value.name.lower()
            
            if filename.endswith('.png'):
                # PNG使用压缩级别
                img.save(output_buffer, format='PNG', compress_level=min(9, self.quality // 10))
                content_type = 'image/png'
            elif filename.endswith('.gif'):
                # GIF不支持质量参数
                img.save(output_buffer, format='GIF')
                content_type = 'image/gif'
            else:
                # JPEG处理
                if img.mode != 'RGB':
                    img = img.convert('RGB')
                img.save(output_buffer, format='JPEG', quality=self.quality)
                content_type = 'image/jpeg'
            
            # 转换为Base64
            compressed_data = output_buffer.getvalue()
            base64_str = base64.b64encode(compressed_data).decode('utf-8')
            return f"data:{content_type};base64,{base64_str}"
            
        except Exception as e:
            print(f"图片处理错误: {str(e)}")
            return None
        finally:
            # 确保图片资源释放
            if 'img' in locals():
                img.close()
class CategorySerializer(serializers.ModelSerializer):
    """类别序列化器"""
    image_base64 = CompressedImageField(
        source='image',
        max_size=(300, 300),
        quality=60,
        read_only=True
    )

    class Meta:
        model = Category
        fields = [
            'id',
            'name',
            'description',
            'address',
            'construction_age',
            'construction_type',
            'layout_orientation',
            'protection_level',
            'image',
            'image_base64',
            'created_at',
            'updated_at'
        ]
        read_only_fields = ['created_at', 'updated_at']
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token['username'] = user.username
        token['role'] = user.role
        token['name'] = user.name
        token['email'] = user.email

        return token

    def validate(self, attrs):
        # 手动验证用户名和密码（跳过父类的自动验证）
        username = attrs.get('username')
        password = attrs.get('password')
         
        user = authenticate(
            request=self.context.get('request'),
            username=username,
            password=password
        )
        
        if not user or not user.is_active:
            raise AuthenticationFailed(
                detail={
                    "error": "authentication_failed",
                    "message": "用户名或密码不正确，请重试",
                    "code": "AUTH_001"
                },
                code="AUTH_001"
            )
        
        # 生成Token
        refresh = self.get_token(user)
        data = {
            "user": UserSerializer(user).data,
            "access": str(refresh.access_token),
            "refresh": str(refresh)
        }
        return data
class UserSerializer(serializers.ModelSerializer):
    
    class Meta:
        model = User
        fields = ('id', 'username', 'name', 'phone_number', 'role')
        read_only_fields = ('id',)
        extra_kwargs = {
            'role': {'write_only': True}  # 只在写入时使用原始值
        }
class DiseaseImageSerializer(serializers.ModelSerializer):
    """病虫害图像子序列化器"""
    class Meta:
        model = DiseaseImage
        fields = ['id', 'image', 'created_at']  # 按需选择返回字段


class CulturalRelicSerializer(serializers.ModelSerializer):
    image_base64 = CompressedImageField(
        source='image',
        max_size=(300, 300),
        quality=60,
        read_only=True
    )
    # 只读嵌套的类别详情
    category = CategorySerializer(read_only=True)

    # 写入时使用的 category_id
    category_id = serializers.PrimaryKeyRelatedField(
        queryset=Category.objects.all(),
        source='category',
        write_only=True,
        required=False,
        allow_null=True
    )

    # 自定义显示病害程度中文
    disease_severity_display = serializers.CharField(
        source='get_disease_severity_display',
        read_only=True,
        label="病害程度（文字）"
    )

    class Meta:
        model = CulturalRelic
        fields = [
            'id',
            'name',
            'image',
            'image_base64',
            'dynasty',
            'country',
            'building_type',
            'other_building_type',
            'category',
            'category_id',
            'disease_types',
            'other_disease_types',
            'disease_severity',
            'disease_severity_display',
            'pattern_types',
            'painting_theme',
            'composition_style',
            'dominant_colors',
            'painting_technique',
            'current_damage_status',
            'hasSpectrum',
            'spectrum_file',
            'hasThreeD',
            'threeD_file',
            'created_by',
            'created_at',
            'last_modified_by',
            'last_modified_at',
        ]
        read_only_fields = [
            'created_by',
            'last_modified_by',
            'last_modified_at'
        ]

class RegisterSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True)
    
    class Meta:
        model = User
        fields = ('username',  'password', 'name')
    
    def create(self, validated_data):
        user = User.objects.create_user(
            username=validated_data['username'],
            password=validated_data['password'],
            name=validated_data.get('name', ''),
        )
        return user



class ChangePasswordSerializer(serializers.Serializer):
    old_password = serializers.CharField(required=True)
    new_password = serializers.CharField(required=True)

class RefreshTokenSerializer(serializers.Serializer):
    refresh = serializers.CharField(required=True)


class VerifyTokenResponseSerializer(serializers.Serializer):
    """验证Token响应序列化器"""
    user = serializers.SerializerMethodField()
    valid = serializers.BooleanField()
    message = serializers.CharField()

    def get_user(self, obj):
        """获取用户信息"""
        return {
            "id": obj.id,
            "username": obj.username,
            "role": obj.role,  # 从用户模型获取角色
            # 添加其他需要的字段（如邮箱、手机号等）
        }

class ChoicesSerializer(serializers.Serializer):
    # ROLE_CHOICES = serializers.SerializerMethodField()
    BUILDING_TYPE_CHOICES = serializers.SerializerMethodField()
    # FUNCTION_CHOICES = serializers.SerializerMethodField()
    # PROTECTION_LEVEL_CHOICES = serializers.SerializerMethodField()
    # PAINTING_LOCATION_CHOICES = serializers.SerializerMethodField()
    # PAINTING_DIRECTION_CHOICES = serializers.SerializerMethodField()
    # PATTERN_CHOICES = serializers.SerializerMethodField()
    # COLOR_CHOICES = serializers.SerializerMethodField()
    # COMPOSITION_CHOICES = serializers.SerializerMethodField()
    # PIGMENT_CHOICES = serializers.SerializerMethodField()
    # BINDER_CHOICES = serializers.SerializerMethodField()
    # GROUND_CHOICES = serializers.SerializerMethodField()
    # TECHNIQUE_CHOICES = serializers.SerializerMethodField()
    # RESTORATION_CHOICES = serializers.SerializerMethodField()
    DISEASE_CHOICES = serializers.SerializerMethodField()
    # SEVERITY_CHOICES = serializers.SerializerMethodField()
    # ENVIRONMENT_CHOICES = serializers.SerializerMethodField()
    # AGE_BASIS_CHOICES = serializers.SerializerMethodField()
    # EQUIPMENT_CHOICES = serializers.SerializerMethodField()
    # LAB_TEST_CHOICES = serializers.SerializerMethodField()
    # FORMAT_CHOICES = serializers.SerializerMethodField()
    # STORAGE_LOCATION_CHOICES = serializers.SerializerMethodField()

    def get_ROLE_CHOICES(self, obj):
        return ROLE_CHOICES

    def get_BUILDING_TYPE_CHOICES(self, obj):
        return BUILDING_TYPE_CHOICES

    def get_FUNCTION_CHOICES(self, obj):
        return FUNCTION_CHOICES

    def get_PROTECTION_LEVEL_CHOICES(self, obj):
        return PROTECTION_LEVEL_CHOICES

    def get_PAINTING_LOCATION_CHOICES(self, obj):
        return PAINTING_LOCATION_CHOICES

    def get_PAINTING_DIRECTION_CHOICES(self, obj):
        return PAINTING_DIRECTION_CHOICES

    def get_PATTERN_CHOICES(self, obj):
        return PATTERN_CHOICES

    def get_COLOR_CHOICES(self, obj):
        return COLOR_CHOICES

    def get_COMPOSITION_CHOICES(self, obj):
        return COMPOSITION_CHOICES

    def get_PIGMENT_CHOICES(self, obj):
        return PIGMENT_CHOICES

    def get_BINDER_CHOICES(self, obj):
        return BINDER_CHOICES

    def get_GROUND_CHOICES(self, obj):
        return GROUND_CHOICES

    def get_TECHNIQUE_CHOICES(self, obj):
        return TECHNIQUE_CHOICES

    def get_RESTORATION_CHOICES(self, obj):
        return RESTORATION_CHOICES

    def get_DISEASE_CHOICES(self, obj):
        return DISEASE_CHOICES

    def get_SEVERITY_CHOICES(self, obj):
        return SEVERITY_CHOICES

    def get_ENVIRONMENT_CHOICES(self, obj):
        return ENVIRONMENT_CHOICES

    def get_AGE_BASIS_CHOICES(self, obj):
        return AGE_BASIS_CHOICES

    def get_EQUIPMENT_CHOICES(self, obj):
        return EQUIPMENT_CHOICES

    def get_LAB_TEST_CHOICES(self, obj):
        return LAB_TEST_CHOICES

    def get_FORMAT_CHOICES(self, obj):
        return FORMAT_CHOICES

    def get_STORAGE_LOCATION_CHOICES(self, obj):
        return STORAGE_LOCATION_CHOICES